package com.example.filedownload;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.StreamProgress;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.Timer;
import java.util.concurrent.TimeUnit;

public class LargeFileDownloader {

    private static final Logger LOGGER = LoggerFactory.getLogger(LargeFileDownloader.class);

    public static void main(String[] args) {
        String fileUrl = "http://localhost:8080/download/ubuntu-20.04.4-desktop-amd64.iso"; // 文件下载URL
        String targetDirectory = "D:/temp/download/"; // 本地保存目录
        String fileName = StrUtil.subAfter(fileUrl, "/", true); // 文件名，可从URL中提取或自定义
        File targetFile = new File(targetDirectory+fileName);
        if (targetFile.exists()) {
            LOGGER.info("文件已存在，删除旧文件");
            FileUtil.del(targetFile);
        }
        File sourceFile = new File("D:/soft/"+fileName);
        long fileSize = sourceFile.length();
        try {
            LOGGER.info("文件开始下载!");
//            downloadFile(fileUrl, targetDirectory, fileName);
            HttpUtil.downloadFile(fileUrl,new File(targetDirectory),new StreamProgress(){

                private long size = 0;
                private long lastSize = 0;
                private Timer timer = new Timer();

                @Override
                public void start() {
                    LOGGER.info("开始下载。。。。");
                    timer.schedule(new java.util.TimerTask() {

                        @Override
                        public void run() {
                             LOGGER.info("已下载：{}%,{}M/秒,总大小:{}", String.format("%.1f", size*100/fileSize*1.0),(size-lastSize)/1024/1024,fileSize);
                             lastSize = size;
                        }
                    }, 1000, 1000);

                }

                @Override
                public void progress(long total, long progressSize) {
                    size = progressSize;
                }


                @Override
                public void finish() {
                    LOGGER.info("下载完成！");
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        LOGGER.error("线程中断",e);
                    }
                    timer.cancel();
                }
            });
            LOGGER.info("文件下载成功!");
//            TimeUnit.SECONDS.sleep(3);
        } catch (Exception e) {
            System.err.println("文件下载失败: " + e.getMessage());
        }
    }

    private static void downloadFile(String fileUrl, String targetDirectory, String fileName) throws IOException {
        URL url = new URL(fileUrl);
        HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
        // 设置请求方法为GET
        httpConnection.setRequestMethod("GET");
        // 输入流是否可用
        httpConnection.setDoInput(true);

        // 响应码检查
        int responseCode = httpConnection.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_OK) {
            // 准备保存文件的路径
            File file = new File(targetDirectory+fileName);
            try (InputStream in = httpConnection.getInputStream();
                 ReadableByteChannel rbc = Channels.newChannel(in)) {
                // 使用NIO进行高效的文件复制
                FileOutputStream fos = new FileOutputStream(file);
                fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
            }catch (Exception e){
                e.printStackTrace();
                throw new IOException("Failed to download file  " + e.getMessage());
            }
        } else {
            throw new IOException("Failed to download file. Server returned HTTP code: " + responseCode);
        }
        httpConnection.disconnect(); // 关闭连接
    }
}
